#include "byte_stream.hh"

// Dummy implementation of a flow-controlled in-memory byte stream.

// For Lab 0, please replace with a real implementation that passes the
// automated checks run by `make check_lab0`.

// You will need to add private members to the class declaration in `byte_stream.hh`

template <typename... Targs>
void DUMMY_CODE(Targs &&... /* unused */) {}

using namespace std;

ByteStream::ByteStream(const size_t capacity) : writen_size(0), read_size(0), capacity_val(capacity), payload("")  { DUMMY_CODE(capacity); }

size_t ByteStream::write(const string &data) {
    DUMMY_CODE(data);
 
    size_t min = std::min(data.length(), remaining_capacity());
    payload += data.substr(0, min);
    writen_size += min;
    return min;
}

//! \param[in] len bytes will be copied from the output side of the buffer
string ByteStream::peek_output(const size_t len) const {
    DUMMY_CODE(len);
    //if (len < 0) {
    //	set_error();
    //}
    return payload.substr(0,len);
}

//! \param[in] len bytes will be removed from the output side of the buffer
void ByteStream::pop_output(const size_t len) {
    //#if (len < 0) {
    //	set_error();
    //}
    size_t ori = payload.length();
    payload.erase(0,len);
    read_size += ori - payload.length() ;
}

//! Read (i.e., copy and then pop) the next "len" bytes of the stream
//! \param[in] len bytes will be popped and returned
//! \returns a string
std::string ByteStream::read(const size_t len) {
    DUMMY_CODE(len);
    string read_str = peek_output(len);
    pop_output(len);

    //if (payload.length() == 0) {
    //	beof = true;
    //}
    return read_str;
}

void ByteStream::end_input() {beof = true;}

bool ByteStream::input_ended() const { return beof; }

size_t ByteStream::buffer_size() const { return payload.length(); }

bool ByteStream::buffer_empty() const { return payload.length() == 0; }

bool ByteStream::eof() const { return beof && buffer_empty(); }

size_t ByteStream::bytes_written() const { return writen_size; }

size_t ByteStream::bytes_read() const { return read_size; }

size_t ByteStream::remaining_capacity() const { return capacity_val - payload.length(); }
